/* $Id: encdb.c 62 2007-05-24 06:10:38Z aldleonm $
 */

#include "encdb.h"
#include "extern.h"
#include "util.h"
#include "file.h"

extern struct _dbi *db_i;
extern struct _dbid *db_id;
extern int debug;


int OpenDB(DB * dbh);
void *QueryDB(DB * dbh, char *qkey, u_int32_t * rsize);
int ListDB(DB * dbh);
int WriteDB(DB * dbh, char *keyname, void *datapart, u_int32_t datasize);
int DeleteDB(DB * dbh, char *qkey);
void CloseDB(DB * dbh);
int StatDB(DB * dbh);

int getID(void);


void License(void)
{
    printf("\n\tThis program is free software; you can redistribute it and/or modify\n ");
    printf("\tit under the terms of the GNU General Public License as published by\n ");
    printf("\tthe Free Software Foundation; either version 2 of the License, or\n ");
    printf("\t(at your option) any later version.\n ");
	printf("\tThis program is distributed in the hope that it will be useful,\n ");
    printf("\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n ");
    printf("\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n ");
    printf("\tGNU General Public License for more details.\n\n");
    printf("\tYou should have received a copy of the GNU General Public License\n ");
    printf("\talong with this program; if not, write to the Free Software Foundation,\n");
    printf("\tInc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.\n\n");
}

void
Usage(void)
{
	printf("%s: %s %s\n", PROGRAM_NAME, PROGRAM_VERSION, CHANGEDATE);
	License();
	printf
		("       desc: copy from file or standard input in to specfied database\n");
	printf("             encrypting it`s content with specified passphrase.\n\n");
	printf("       author: %s, email: %s\n", AUTHORS_NAMES, AUTHORS_EMAILS);
	printf("\n");
	printf("       options:\n");
	printf("         -f <dbfilename> -p <ask|file:pathname> -N <dbname> -c [-g] \n");
	printf("         -f <dbfilename> -p <ask|file:pathname> -N <dbname> -s \n");
	printf
		("         -f <dbfilename> -p <ask|file:pathname> -N <dbname> -o <writeout> -n <keyname> [-g]  \n");
	printf
		("         -f <dbfilename> -p <ask|file:pathname> -N <dbname> -i <readfrom> -n <keyname> [-g] \n");
	printf
		("         -f <dbfilename> -p <ask|file:pathname> -N <dbname> -d -n <keyname> [-g] \n");
	printf
		("         -f <dbfilename> -p <ask|file:pathname> -N <dbname> -l -N <dbname> [-g] \n\n");

	printf("       The option -p can read files ( -p file:/pathtofile ) and named pipes\n");
	printf("       ( same as a file ) , or prompt and ask for a password ( -p ask ).\n\n");

	printf("       The option -i takes input from a file or stdin if passed \"-\" as argument.\n");
	printf("       The option -o dumps to file or stdout if passed \"-\" as argument.\n\n");
}

int
main(int argc, char *argv[])
{

	FILE *iofile = 0;
	char DBFilename[BSZ];
	char RFilename[BSZ];
	char WFilename[BSZ];
	char KNString[BSZ];
	char *tmp_passwd = NULL;

	char ch;
	int ret;
	struct stat fst;
	u_int32_t fsize = 0;

	memset(RFilename, 0, BSZ);
	memset(WFilename, 0, BSZ);
	memset(KNString, 0, BSZ);
	memset(DBFilename, 0, BSZ);


	/* extern */
	db_i->action = -1;

	while ((ch = getopt(argc, argv, "f:o:i:p:n:N:cldhvgs")) != EOF)
		switch (ch) {
				case 'f':
					if ((strncpy(db_i->fname, optarg, strlen(optarg) + 1)) == NULL)
						Perrx(3, "Error setting option.", 0);
					db_i->s_fname = strlen(optarg) + 1;
					break;
				case 'o':
					if ((strncpy(RFilename, optarg, BSZ)) == NULL)
						Perrx(3, "Error setting option.", 0);
					RFilename[0] == '-' ? (db_i->action_subopt = 1) : (db_i->action_subopt = 0);
					db_i->action = READ;
					break;
				case 'c':
					db_i->action = CREATE;
					break;
				case 'p':
					tmp_passwd = Alloc(STRSZ);
					if ((strncpy(tmp_passwd, optarg, strlen(optarg) + 1)) != NULL) {
						if ( (db_i->passw = getPass(tmp_passwd)) == NULL ) {
							exit(1);	
						}
					}
					break;
				case 'i':
					if ((strncpy(WFilename, optarg, strlen(optarg))) == NULL)
						Perrx(3, "Error setting option.", 0);
					WFilename[0] == '-' ? (db_i->action_subopt = 1) : (db_i->action_subopt = 0);
					db_i->action = WRITE;
					break;
				case 'd':
					db_i->action = DELETE;
					break;
				case 'n':
					if ((strncpy(KNString, optarg, strlen(optarg))) == NULL)
						Perrx(3, "Error setting option.", 0);
					break;
				case 'h':
					Usage();
					exit(1);
					break;
				case 'v':
					printf("%s: %s %s %s %s\n", PROGRAM_NAME, PROGRAM_VERSION, CHANGEDATE, AUTHORS_NAMES, AUTHORS_EMAILS);
					License();
					before_exit(NULL);
					exit(-1);
					break;
				case 'g':
					debug = 1;
					break;
				case 'N':
					if ((strncpy(db_i->name, optarg, strlen(optarg) + 1)) == NULL)
						Perrx(3, "Error setting option, exiting..", 0);
					db_i->name[strlen(optarg) + 1] = "\0";	/* XXX */
					db_i->s_name = strlen(optarg) + 1;
					break;
				case 'l':
					db_i->action = LIST;
					break;
				case 'L':
					db_i->action = LIST;
					db_i->action_subopt = 1;
					break;
				case 's':
					db_i->action = STAT;
					break;
				default:
					Usage();
					exit(1);
		}


	if (db_i->action == -1) {
		Usage();
		exit(1);
	}

	/* create DB obj. */
	if ((ret = db_create(&db_i->pdb, NULL, 0)) != 0) {
		Perrx(1, "Error creating db handle. exiting...", 0);
	}
	/* open dbfile */
	if ((ret = OpenDB(db_i->pdb)) != 0) {
		Perrx(1, "Error opening db. exiting...", 0);
	}

	if (db_i->action != CREATE && getID() != 0) {
		Perrx(1, "Error getting database id. exiting...", 0);
	}

	if (db_i->action == CREATE) {
		before_exit(NULL);
		exit(0);
	}

/* IF-ELSE Block Write START */
/* Write into dbase  */
	/* if read from file */
	if (db_i->action == WRITE && db_i->action_subopt == 0) {
		/* openfile */
		if ((iofile = fopen(WFilename, "r")) == NULL) {
			Perrx(1, "main(): unsuccessful call to fopen().", 1);
		}
		/* get the file size */
		if ((fstat(fileno(iofile), &fst)) != 0) {
			Perrx(1, "main(): unsuccessful call to fstat().", 1);
		} else {
			fsize = fst.st_size;
		}
		if ((WriteDB(db_i->pdb, KNString, _my_readf(iofile), fsize))) {
			Perrx(1, "main(): unsuccessful call to WriteDB().", 0);
		}
		fclose(iofile);
		before_exit(NULL);
		exit(0);
		/* if read from stdinput */
	} else if (db_i->action == WRITE && db_i->action_subopt == 1) {
		u_int32_t tmp_Size = 0;
		void *tmp_StdO = _my_readstdin(&tmp_Size);

		if ((WriteDB(db_i->pdb, KNString, tmp_StdO, tmp_Size))) {
			Perrx(1, "main(): unsuccessful call to WriteDB().", 0);
		}
		before_exit(tmp_StdO);
		exit(0);
	}
/* IF-ELSE Block Write END */

/* IF-ELSE Block Read START */
/* Read from dbase */
	/* match key from database, opt write to file it`s content */
	if (db_i->action == READ && db_i->action_subopt == 0) {
		if (((iofile = fopen(RFilename, "w+")) == NULL)) {
			Perrx(1, "main(): unsuccessful call to fopen().", 1);
		}

		void *tmp_Qout = NULL;
		u_int32_t size = 0;

		if ((tmp_Qout = QueryDB(db_i->pdb, KNString, &size)) == NULL) {
			Perrx(1, "main(): unsuccessful call to QueryDB().", 0);
		}

		if ((fwrite(tmp_Qout, 1, size, iofile)) != size) {
			Perrx(4, "main(): unsuccessful to fwrite().", 1);
		}
		before_exit(tmp_Qout);
		fclose(iofile);
		exit(0);
		/* output to stdout */
	} else if (db_i->action == READ && db_i->action_subopt == 1) {
		void *tmp_Qout = NULL;
		u_int32_t size = 0;

		if ((tmp_Qout = QueryDB(db_i->pdb, KNString, &size)) == NULL) {
			Perrx(1, "main(): unsuccessful call to QueryDB().", 0);
		}

		/* fprintf(stdout, "%s", (char *) memcpy(tmp_out, tmp_Qout, size)); */
		fprintf(stdout, "%s", tmp_Qout, size);
		fflush(stdout);
		before_exit(tmp_Qout);
		exit(0);
	}
/* IF-ELSE Block Read END */

/* IF-ELSE Block START */
/* delete entry from database */
	if (db_i->action == DELETE) {
		if ((DeleteDB(db_i->pdb, KNString)) != 0) {
			Perrx(1, "main(): unsuccessful call to DeleteDB().", 0);
		}
		before_exit(NULL);
		exit(0);

/* list entries */
	} else if (db_i->action == LIST) {
		if ((ListDB(db_i->pdb)) != 0) {
			Perrx(1, "main(): unsuccessful call to ListDB().", 0);
		}
		before_exit(NULL);
		exit(0);
/* print stats */
	} else if (db_i->action == STAT) {

		if ((StatDB(db_i->pdb)) != 0) {
			Perrx(1, "main(): unsuccessful call to StatDB().", 0);
		}

		struct _dbid *tmp_dbid;
		u_int32_t size;

		if ((tmp_dbid = QueryDB(db_i->pdb, ID_KEY, &size)) == NULL) {
			Perrx(1, "main(): unsuccessful call to QueryDB().", 0);
		}

		fprintf(stdout, "Id of %s...\n", tmp_dbid->name);
		fprintf(stdout, "creation date: %s", ctime(&tmp_dbid->creation_date));
		fprintf(stdout, "last change date: %s\n", ctime(&tmp_dbid->last_change));

		before_exit(tmp_dbid);
		exit(0);
	}
/* IF-ELSE Block END */

	/* NOT REACHED */
	return 0;
}

/* vim: ts=4
 * END
 */
